package com.kstudio.videocapture.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;

import android.os.Handler;
import android.os.Message;

public class KhFile {
    private final KLog log = new KLog("KFileList");

    public static final int         MODE_COPY   = 0x0001;
    public static final int         MODE_MOVE   = 0x0002;
    public static final int         MODE_DELETE = 0x0003;

    private static final int        MSG_PROGRESS   = 0x0001;
    private static final int        MSG_COMPLETE   = 0x0002;
    private static final int        MSG_CANCEL     = 0x0003;
    private static final int        MSG_ERROR      = 0x0004;

    private FileThread     mThread;
    private KhFileListener mListener;

    public interface KhFileListener {
        void onProgress(int progress);
        void onComplete();
        void onCancel();
        void onError();
    }

    public static String pathToName(String path) {
        int separatorIndex = path.lastIndexOf(File.separator);
        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
    }

    public static KhFile copy(ArrayList<String> source, String targetDirectory, KhFileListener l) {
        return new KhFile(MODE_COPY, source, targetDirectory, l);
    }

    public void cancel() {
        if(mThread != null) mThread.cancel();
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_PROGRESS:
                    progress(msg.arg1);
                break;
                case MSG_COMPLETE:
                    complete();
                break;
                case MSG_CANCEL:
                    cancel_();
                break;
                case MSG_ERROR:
                    error();
                break;
            }
        }
    };

    private KhFile(int mode, ArrayList<String> source, String targetDirectory, KhFileListener l) {
        mListener = l;

        mThread = new FileThread(mode, source, targetDirectory);
        mThread.start();
    }

    private void progress(int progress) {
        if(mListener != null) mListener.onProgress(progress);
    }

    private void complete() {
        if(mListener != null) mListener.onComplete();
    }

    private void cancel_() {
        if(mListener != null) mListener.onCancel();
    }

    private void error() {
        if(mListener != null) mListener.onError();
    }

    private class FileThread extends Thread {
        private int                 mMode;
        private ArrayList<String>   mSource;
        private int                 mSize;
        private String              mTagetDirectory;

        public boolean running;

        public void cancel() {
            log.e("fcin cancel");
            running = false;
            try { fcout.close();} catch (IOException ioe) {}
            try { fcin.close(); } catch (IOException ioe) {log.e("fcin 3");}
            try { outputStream.close();} catch (IOException ioe) {}
            try { inputStream.close(); } catch (IOException ioe) {}
        }

        public FileThread(int mode, ArrayList<String> source, String targetDirectory) {
            super();
            running = true;

            mMode = mode;
            mSource = source;
            mTagetDirectory = targetDirectory;
            mSize = mSource.size();
        }

        @Override
        public void run() {
            for(int i = 0; i < mSize; i++) {
                if(!running) {
                    mHandler.sendEmptyMessage(MSG_CANCEL);
                    break;
                }
                String src = mSource.get(i);

                if(mMode == MODE_COPY) {
                    if(copy(src, mTagetDirectory + File.separator + pathToName(src))) {
                        log.e("fcin true");
                        Message msg = mHandler.obtainMessage();
                        msg.what = MSG_PROGRESS;
                        msg.arg1 = i + 1;
                        mHandler.sendMessage(msg);
                    } else {
                        log.e("fcin false");
                        mHandler.sendEmptyMessage(MSG_ERROR);
                        break;
                    }
                } else if(mMode == MODE_MOVE) {
//                    log.d("MODE_MOVE mSource = %s mTaget = %s", mSource, mTaget);
//                    File sourceFile = new File(mSource);
//                    File tagetFile  = new File(mTaget);
//
//                    sourceFile.renameTo(tagetFile);
//                    log.d("MODE_MOVE renameTo");
//
//                    running = false;
//                    mHandler.sendEmptyMessage(MSG_COMPLETE);
                } else if(mMode == MODE_DELETE) {
//                    File sourceFile = new File(mSource);
//
//                    if(sourceFile.exists())
//                        sourceFile.delete();
//
//                    running = false;
//                    mHandler.sendEmptyMessage(MSG_COMPLETE);
                }
            }

            if(running) mHandler.sendEmptyMessage(MSG_COMPLETE);
        }
        FileChannel fcin = null;
        FileChannel fcout = null;
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        private boolean copy(String source, String target) {
            boolean results = false;

            File sourceFile = new File(source);



            try {
                inputStream = new FileInputStream(sourceFile);
                outputStream = new FileOutputStream(target);

                fcin = inputStream.getChannel();
                fcout = outputStream.getChannel();

                long size = fcin.size();
                fcin.transferTo(0, size, fcout);
                log.e("fcin 2");
                results = true;
            } catch (Exception e) {
                e.printStackTrace();
                results = false;
            } finally {
                try { fcout.close();} catch (IOException ioe) {}
                try { fcin.close(); } catch (IOException ioe) {log.e("fcin 3");}
                try { outputStream.close();} catch (IOException ioe) {}
                try { inputStream.close(); } catch (IOException ioe) {}
            }
            return results;
        }

        @SuppressWarnings("unused")
        private void streamCopy(String source, String target) {
            File sourceFile = new File( source );

            FileInputStream inputStream = null;
            FileOutputStream outputStream = null;

            try {
                inputStream = new FileInputStream(sourceFile);
                outputStream = new FileOutputStream(target);

                int bytesRead = 0;

                byte[] buffer = new byte[1024];
                while ((bytesRead = inputStream.read(buffer, 0, 1024)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally{
                try{
                    outputStream.close();
                }catch(IOException ioe){

                }

                try{
                    inputStream.close();
                }catch(IOException ioe){

                }
            }
        }

        @SuppressWarnings("unused")
        private void bufferCopy(String source, String target) {
              File sourceFile = new File(source);

              FileInputStream inputStream = null;
              FileOutputStream outputStream = null;
              BufferedInputStream bin = null;
              BufferedOutputStream bout = null;

              try {
                  inputStream = new FileInputStream(sourceFile);
                  outputStream = new FileOutputStream(target);

                  bin = new BufferedInputStream(inputStream);
                  bout = new BufferedOutputStream(outputStream);

                  int bytesRead = 0;
                  byte[] buffer = new byte[1024];
                  while ((bytesRead = bin.read(buffer, 0, 1024)) != -1) {
                      bout.write(buffer, 0, bytesRead);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try{
                      outputStream.close();
                  }catch(IOException ioe){

                  }
                  try{
                      inputStream.close();
                  }catch(IOException ioe){

                  }
                  try{
                      bin.close();
                  }catch(IOException ioe){

                  }

                  try{
                      bout.close();
                  }catch(IOException ioe){

                  }
              }
        }

        @SuppressWarnings("unused")
        private void ChannelCopy(String source, String target) {
            File sourceFile = new File(source);

            FileInputStream inputStream = null;
            FileOutputStream outputStream = null;
            FileChannel fcin = null;
            FileChannel fcout = null;

            try {
                inputStream = new FileInputStream(sourceFile);
                outputStream = new FileOutputStream(target);

                fcin = inputStream.getChannel();
                fcout = outputStream.getChannel();

                long size = fcin.size();
                fcin.transferTo(0, size, fcout);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fcout.close();
                } catch (IOException ioe) {

                }
                try {
                    fcin.close();
                } catch (IOException ioe) {

                }
                try {
                    outputStream.close();
                } catch (IOException ioe) {

                }
                try {
                    inputStream.close();
                } catch (IOException ioe) {

                }
            }
        }

    }
}
